﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MicroMq.Helper
{
    class SortedQueue<T>
    {
        private readonly List<T> data;

        private readonly IComparer<T> comparer;
        public SortedQueue()
        {
            data = new List<T>();
        }
        public SortedQueue(IComparer<T> comparer)
        {
            this.comparer = comparer;
            data = new List<T>();
        }

        public int Count => data.Count;
        public void Enqueue(T item)
        {
            lock (this)
            {
                data.Add(item);
                if (comparer == null)
                {
                    data.Sort();
                }
                else
                {
                    data.Sort(comparer);
                }
            }

        }

        private T First(bool isRemove)
        {
            if (isRemove)
            {
                lock (this)
                {
                    if (data.Count > 0)
                    {
                        var result = data[0];
                        data.RemoveAt(0);
                        return result;
                    }
                }
            }
            else
            {
                if (data.Count > 0)
                {
                    return data[0];
                }
            }
            return default;
        }

        public T Get(Func<T, bool> predicate)
        {
            return data.FirstOrDefault(predicate);
        }

        public T Dequeue()
        {
            if (Count == 0)
            {
                throw new IndexOutOfRangeException("没有元素");
            }
            return First(true);
        }

        public T Peek()
        {
            if (Count == 0)
            {
                throw new IndexOutOfRangeException("没有元素");
            }
            return First(false);
        }


        public bool TryDequeue(out T item)
        {
            if (Count == 0)
            {
                item = default;
                return false;
            }
            item = First(true);
            return true;
        }

        public bool TryPeek(out T item)
        {
            if (Count == 0)
            {
                item = default;
                return false;
            }
            item = First(false);
            return true;
        }


    }
}
